# -*- coding: utf-8 -*-
import openerp
from openerp.osv import osv
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.tools.safe_eval import safe_eval as eval
from werkzeug.datastructures import FileStorage
from openerp import SUPERUSER_ID
import simplejson
import random
import time
import datetime
import os
import base64
import sys
import jinja2
from openerp import tools
from openerp.tools.float_utils import float_round



if hasattr(sys, 'frozen'):
    # When running on compiled windows binary, we don't have access to package loader.
    path = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'html'))
    loader = jinja2.FileSystemLoader(path)
else:
    loader = jinja2.PackageLoader('openerp.addons.dftg_ext', "html")

env = jinja2.Environment('<%', '%>', '${', '}', '%', loader=loader, autoescape=True)


class PositionControllers(http.Controller):

    def _check_domain(self, model, domain):
        try:
            model_columns = request.registry[model].fields_get(request.cr, SUPERUSER_ID)
            domain = eval(domain)
            if not isinstance(domain, list):
                raise ValueError()

            for item in domain:
                if item == '|':
                    continue

                if not isinstance(item, (list, tuple)):
                    raise ValueError()

                if item[0] not in model_columns:
                    raise ValueError()

                if len(item) != 3:
                    raise ValueError()
        except:
            raise osv.except_osv(u'错误', '无法解析的domain条件%s' % domain)

    def _check_model(self, model):
        try:
            request.registry[model]
        except KeyError:
            raise osv.except_osv(u'错误', u'Model %s不存在' % model)

    @http.route('/editor/many2one/search', auth='public')
    def many2one_search(self, shop_id, word, model, domain=None):
        cr, context, pool = request.cr, request.context, request.registry
        self._check_model(model)

        domain = eval(domain or '[]')
        if domain:
            self._check_domain(model, domain)

        if model == 'product.template':
            domain.extend([
                ('shop_id', '=', int(shop_id)),
                ('is_online', '=', True),
                '|',
                ('product_id.name', 'ilike', word),
                ('product_id.default_code', 'ilike', word),
            ])

            shop_obj = pool.get('shop.line')
            shop_ids = shop_obj.search(cr, SUPERUSER_ID, domain, context=context)

            return request.make_response(simplejson.dumps([
                {
                    'id': line.product_id.id, 'value': line.product_id.name
                } for line in shop_obj.browse(cr, SUPERUSER_ID, shop_ids, context=context)
            ]))

        elif model in ('mshop.article', 'mshop.ad.wall'):
            domain.append(('shop_id', '=', int(shop_id)))

        return request.make_response(simplejson.dumps([
            {
                'id': record[0], 'value': record[1]
            } for record in pool.get(model).name_search(cr, SUPERUSER_ID,
                                                        word, args=domain, limit=20, context=context)
        ]))

    @http.route('/editor_image', auth='public')
    def editor_image(self, filename):
        if filename and filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')):
            main_direction = tools.config.filestore(request.cr.dbname)
            if (not os.path.isfile(filename)):
                filename = os.path.join(main_direction, filename)

            if (not os.path.isfile(filename)):
                return ''

            with open(filename) as img:
                response = request.make_response(img.read())
                suffix = filename[filename.rfind('.') + 1:]

                response.headers['Content-Type'] = 'image/' + suffix
                response.headers['Content-Disposition'] = 'attachment;filename=%s' % filename.encode('utf-8')

                return response

        return ''

    @http.route('/editor/get', auth='public')
    def editor_get(self, osv_info, editor_id):
        cr, context, pool = request.cr, request.context, request.registry

        osv_info = simplejson.loads(osv_info)
        return request.make_response(simplejson.dumps(
            [{
                'id': row.id,
                'index': row.index,
                'value': row.value,
                'component': row.component,
            } for row in getattr(pool.get(osv_info.get('model', 'product.template')).browse(
                cr, SUPERUSER_ID, int(editor_id), context=context), osv_info.get('field', 'description_editor_ids'))]
        ))

    @http.route('/editor/wall/get_desc', auth='public')
    def wall_get_desc(self, wall_id):
        cr, context, pool = request.cr, request.context, request.registry

        wall = pool.get('mshop.ad.wall').browse(cr, SUPERUSER_ID, int(wall_id), context=context)

        return request.make_response(simplejson.dumps({
            'wall': [{
                'img': '/website/image/mshop.ad.wall.line/%s/image' % line.id,
                'title': line.name
            } for line in wall.line_ids],
            'type': wall.type,
        }))

    @http.route('/editor/article/get_desc', auth='public')
    def article_get_desc(self, article_id):
        cr, context, pool = request.cr, request.context, request.registry

        article = pool.get('mshop.article').browse(cr, SUPERUSER_ID, int(article_id), context=context)

        return request.make_response(simplejson.dumps({
            'img': '/website/image/mshop.article/%s/image' % article_id,
            'title': article.name
        }))

    @http.route('/editor/product/get_desc', auth='public')
    def product_get_desc(self, product_id):
        cr, context, pool = request.cr, request.context, request.registry

        product = pool.get('product.template').browse(cr, SUPERUSER_ID, int(product_id), context=context)

        return request.make_response(simplejson.dumps({
            'img': '/website/image/product.template/%s/image' % product_id,
            'price': product.list_price,
        }))

    def _generate_image_path(self, model, editor_id, file):
        if not file or not isinstance(file, FileStorage):
            return ''

        def make_dir(main_direction, direction):
            direction = os.path.join(main_direction, direction)
            if not os.path.exists(direction):
                os.mkdir(direction)

            if not os.path.isdir(direction):
                raise ValueError(u'错误, 默认图片文件夹%s已经存在且不是文件夹' % direction)

        cr, context, pool = request.cr, request.context, request.registry
        direction = pool.get('ir.config_parameter').get_param(cr, SUPERUSER_ID, 'dftg_ext.editor_image_folder')
        if direction:
            if not os.path.exists(direction) or not os.path.isdir(direction):
                raise ValueError(u'错误，系统配置中获取到的路径不不是文件夹或不存在')
        else:
            main_direction = tools.config.filestore(cr.dbname)
            img_direction = 'editor_image'
            first_direction = os.path.join(img_direction, editor_id[0:2])
            direction = os.path.join(first_direction, editor_id)

            make_dir(main_direction, img_direction)
            make_dir(main_direction, first_direction)
            make_dir(main_direction, direction)

        filename = os.path.join(direction, model + editor_id + file.filename)
        file.save(os.path.join(main_direction, filename))
        return 'editor_image?filename=' + filename

    @http.route('/editor/save', auth='public')
    def editor_save(self, osv_info, editor_id, delete_items, **args):
        cr, context, pool = request.cr, request.context, request.registry
        osv_info = simplejson.loads(osv_info)
        editor_row_obj = pool.get(osv_info.get('model_line', 'description.editor.row'))

        res = []
        image_id_keys = filter(lambda item: item.endswith('-id'), args.keys())

        for index in range(len(args) - len(image_id_keys)):
            item = args.get(str(index), None)
            write_val, create_val = {}, {}
            write_id = False
            if str(index) + '-id' in args:
                write_id = simplejson.loads(args[str(index) + '-id']).get('id')
                if write_id:
                    write_val = {'index': index}
                else:
                    create_val = {
                        osv_info.get('editor_field', 'product_id'): int(editor_id),
                        'value': self._generate_image_path(osv_info.get('model', 'product.template'), editor_id, item),
                        'index': index,
                        'component': 'image-input',
                    }
            elif item:
                item = simplejson.loads(item)
                if item.get('id'):
                    write_id = item.get('id')
                    write_val = {
                        'value': item.get('value'),
                        'index': index,
                    }
                else:
                    create_val = {
                        osv_info.get('editor_field', 'product_id'): int(editor_id),
                        'value': item.get('value'),
                        'index': index,
                        'component': item.get('component'),
                    }

            if write_val:
                editor_row_obj.write(cr, SUPERUSER_ID, int(write_id), write_val, context=context)

            if create_val:
                res.append([index, editor_row_obj.create(cr, SUPERUSER_ID, create_val, context=context)])

        if delete_items:
            delete_items = map(int, simplejson.loads(delete_items))
            editor_row_obj.unlink(cr, SUPERUSER_ID, delete_items, context=context)

        cr.commit()
        return request.make_response(simplejson.dumps(res))

    # 手工的创建地址
    @http.route('/position/set_path', auth='public')
    def create_path(self, picking_id):
        cr, context, pool = request.cr, request.context, request.registry
        position_obj = pool.get('stock.position')
        x, y = 31.267836, 121.651970

        while True:
            plus_x, plus_y = x + (random.randint(1, 10) - 5) / 200.0, y + (random.randint(1, 10) - 5) / 200.0

            position_obj.create(cr, SUPERUSER_ID, {
                'latitude': plus_x,
                'longitude': plus_y,
                'precision': 50,
                'user_id': 1,
                'picking_id': int(picking_id),
            }, context=context)

            cr.commit()
            time.sleep(30)

    @http.route('/position/last_gps_position', auth='public')
    def get_last_gps_position(self):
        cr, context, pool = request.cr, request.context, request.registry
        cr.execute('''
            SELECT MAX(id) FROM gps_position GROUP BY vehicle
        ''')

        records = pool.get('gps.position').read(
            cr, SUPERUSER_ID, [one[0] for one in cr.fetchall()],
            ['direction', 'vehicle', 'lat', 'lon', 'placename', 'waiting_time'], context=context)

        return request.make_response(simplejson.dumps(records))

    @http.route('/position/get_path', auth='public')
    def get_path(self, picking_id, items_pair, zoom, create_date=None, **kw):
        cr, context, pool = request.cr, request.context, request.registry
        position_obj = pool.get('stock.position')
        picking_id, items_pair, zoom = int(picking_id), int(items_pair), int(zoom)

        if create_date:
            position_ids = position_obj.search(cr, SUPERUSER_ID, [('picking_id', '=', picking_id),
                                                                  ('create_date', '>', create_date)], limit=items_pair, order='create_date asc', context=context)
        else:
            position_ids = position_obj.search(cr, SUPERUSER_ID, [('picking_id', '=', picking_id)],
                                               limit=items_pair, order='create_date desc')
            position_ids.reverse()

        if position_ids:
            # 使用orm读取的create_date字段精度不够，会造成不停的加载的问题
            position_ids = tuple(position_ids)
            cr.execute('''
                    select latitude, longitude, create_date from stock_position where id in %s
                ''' % (len(position_ids) == 1 and str(position_ids).replace(',', '') or str(position_ids)))
            res = cr.dictfetchall()
        else:
            res = []

        return request.make_response(simplejson.dumps(res))

    @http.route('/position/get_delivery_path', auth='public')
    def get_delivery_path(self, days=0, **kw):
        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
        # selected_date = (datetime.date.today() + datetime.timedelta(days=int(days) - 1)).strftime('%Y-%m-%d')
        # next_selected_date = (datetime.date.today() + datetime.timedelta(days=int(days))).strftime('%Y-%m-%d')

        current_days = (datetime.date.today() + datetime.timedelta(days=int(days))).strftime('%Y-%m-%d')
        # 似乎时区有点问题
        # selected_date += ' 16:00:00'
        # next_selected_date += ' 16:00:00'

        order_obj = pool.get('stock.picking')
        order_ids = order_obj.search(cr, uid, [('expected_delivery_time', '=', current_days),
                                               ('state', 'not in', ('cancel', 'draft')),
                                               '|', ('picking_type_code', '=', 'outgoing'),
                                               '&', ('picking_type_code', '=', 'incoming'),
                                                ('shipping_type_sale', '=', 'self_logistics'),
                                               ],
                                     order='expected_delivery_time asc', context=context)

        res = []
        for order in order_obj.browse(cr, uid, order_ids, context=context):
            res.append({
                'id': order.id,
                'address': pool.get('stock.picking')._get_address_by_order(order),
                'partner': order.partner_id.name,
                'order': order.so_id and order.so_id.name or order.po_id and order.po_id.name or '',
                'invisible': order.is_invisible_in_map,
                'picking_type_code': order.picking_type_code
            })

        return request.make_response(simplejson.dumps(res))

    def _get_purchase_line_info(self, order):
        res = '<p><strong>%s</strong>(%s)</p>' % (order.name, order.supplier_address)
        for line in order.order_line:
            res += '<p>产品名称:%s-数量:%s-单价:%s（备注:%s）</p>' % (line.product_id.name, line.product_qty, line.price_unit, line.prod_spec or u'无')

        return res

    @http.route('/position/get_purchase_delivery_path', auth='public')
    def get_purchase_delivery_path(self, days=0, **kw):
        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
        current_days = (datetime.date.today() + datetime.timedelta(days=int(days))).strftime('%Y-%m-%d')

        order_obj = pool.get('purchase.order')
        order_ids = order_obj.search(cr, uid, [
            ('planned_delivery_date', '=', current_days),
            ('is_self_pickup', '=', True),
            ('supplier_address', '!=', False)],
            order='planned_delivery_date asc', context=context)

        res = []
        for order in order_obj.browse(cr, uid, order_ids, context=context):
            res.append({
                'id': order.id,
                'address': order.supplier_address,
                'partner': order.partner_id.name,
                'order': order.name,
                'line_info': self._get_purchase_line_info(order),
            })

        return request.make_response(simplejson.dumps(res))

    @http.route('/position/get_delivery_position_view', auth='public')
    def get_delivery_position_view(self, **kw):
        template = env.get_template('delivery_position.html')
        return template.render({})

    @http.route('/position/invisible', auth='public')
    def position_invisible(self, id, invisible):
        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry

        pool.get('stock.picking').write(cr, uid, int(id), {
            'is_invisible_in_map': invisible == 'true',
        }, context=context)

    @http.route('/api/v1/order/<string:order_name>/money', auth='public')
    def api_get_order_money(self, order_name, **kwargs):
        """
        #IL5CT 写一个api接口用于获取订单信息给商城调用，/api/v1/order/S20180xxx/money，暂时允许public权限
        {
            "errcode":0,
           "errmsg":"ok" ,
            "订单号": S20180xxxx,
            "成交总价": 总价
            "原价总价": 所有订单行商品原价单价X数量相加
        }
        """
        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
        error_message, order_dict = '', {}
        for order_dict in pool.get('sale.order').search_read(cr, SUPERUSER_ID, [('name', '=', order_name)],
                                                             ['order_line', 'name', 'amount_total'], context=context):
            original_cost = 0
            for line in pool.get('sale.order.line').search_read(cr, SUPERUSER_ID, [('id', 'in', order_dict.get('order_line'))],
                                                        ['product_uom_qty', 'origin_price'], context=context):
                original_cost += line.get('product_uom_qty') * line.get('origin_price')
            if original_cost:
                return request.make_response(simplejson.dumps({
                    'errmsg': 'ok',
                    'errcode': 0,
                    '订单号': order_dict.get('name'),
                    '成交总价': round(order_dict.get('amount_total'), 2),
                    '原价总价': round(original_cost, 2),
                }))
            else:
                error_message = '此订单没有产品'
                errcode = 1002
        if not order_dict:
            errcode = 1001
            error_message = '订单号不存在'
        return request.make_response(simplejson.dumps({'errcode': errcode or 1001, 'errmsg': error_message}))